home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Essentials / MacApp Documentation / MacApp.TECH$ Archives / 1991 / Jan 91 / MacApp.Tech$ 1⁄4⁄91 / 2571-A more elegant clipb-Jan91 < prev    next >
Encoding:
Text File  |  1991-03-06  |  6.2 KB  |  182 lines  |  [TEXT/GEOL]

  1. Item    3997645                         1-Jan-91        13:53GMT
  2.  
  3. From:   UK0392                          EHN & DIJ Oakley,BDV
  4.  
  5. To:     UK.DTS                          UK Developer Technical Support
  6.  
  7. cc:     MACAPP.TECH$                    MacApp Technical
  8.  
  9. ------------------------------------------------------------------------------
  10.  
  11. Sub:    A more elegant clipboard prob
  12.  
  13. Friends,
  14.  
  15. If you are looking for a little mental problem with which to see the New Year
  16. in, here is one which has been tickling me for a few hours, in getting the
  17. MacApp clipboard handling routines to cope with rather complex and different
  18. views:
  19.  
  20. We are currently moving an application into V3.0, which allows a user to edit a
  21. 'panel' design for manufacture, using MacApp 2.0.1. Up to V2.0, we represented
  22. the panel as TDocument, to which there were two TWindows, one a simple text
  23. view, the other a graphical one. With V3.0, we have turned the text view into a
  24. complex spreadsheet-like view, with the following overall hierarchy:
  25.  
  26.               TPanlGWindow - graphics view
  27.              /
  28. TPanlDocument
  29.              \
  30.               TPanlTWindow - spreadsheet view
  31.                      |
  32.    TBaseView ( <-TView ) ------- simple view to make things easier
  33.                      |
  34.       -----------------------------------------------------
  35.       |                                                   |
  36.  TPrimaryScroller (from USynchScroller)                   |
  37.       |                                                   |
  38.  TPanlTView ( <-TTextGridView ) - 2-col coordinate data   |
  39.                                                           |
  40.       --------------------------------------------------------
  41.       |                                                       |
  42.  TSecondaryScroller                                     (2 others likewise)
  43.       |
  44.  TRowsView ( <-TTextGridView ) - 1-col row numbering
  45.  
  46. - and TBaseView also has a few subsidiary TStaticText and TEditText views!
  47.  
  48. By and large, this works very nicely (if a little finnicky in places), and
  49. USynchScroller does its job beautifully (thanks, Larry Tesler). The pain comes
  50. with Clipboard commands. We wanted to cut/copy the entire load to the
  51. clipboard, so that when the user opens the clipboard, he sees an identical set
  52. of linked scrolling views, as anything else would have been confusing and
  53. unmanageable for them.
  54.  
  55. We implemented this by the following skeletal code:
  56.  
  57. PROCEDURE TCutRCommand.ICutRCommand(...);
  58. BEGIN
  59.    ICommand(...);
  60.  {set up the various fields}
  61.  {create the data structure containing the copied data}
  62. END;
  63.  
  64. PROCEDURE TCutRCommand.DoIt; OVERRIDE;
  65. VARclipPanlView:   TBaseView;
  66.    clipDoc:TPanlDocument;
  67.    aSize, aPos:    VPoint;
  68.    count:  INTEGER;
  69.    outline:Rect;
  70.    fi: FailInfo;
  71.  
  72.    PROCEDURE CopyToClip;
  73.    VAR aNewPanl:   TPanl;
  74.    BEGIN
  75.    aNewPanl := TPanl(fThePanl.Clone);
  76.    FailNil(aNewPanl);
  77.   {and set up the handle fields too}
  78.    clipDoc.fPanl := aNewPanl;
  79.    END;
  80.  
  81.    PROCEDURE HdlFailure(error: OSErr; message: LONGINT);
  82.    BEGIN
  83.    clipDoc.Free;
  84.    END;
  85.  
  86. BEGIN
  87.  {cut the data out of the original panel}
  88.  {now, initialise our Clipboard version of TPanlDocument}
  89.    New(clipDoc);
  90.    FailNIL(clipDoc);
  91.    clipDoc.IPanlDocument(TRUE);
  92.    fClipDocument := clipDoc;
  93.  
  94.    CatchFailures(fi, HdlFailure);
  95.  
  96.  {DoClipViews actually uses the resource view to construct those views
  97.  needed for the clipDoc - it is v similar to DoMakeViews, but a bit more
  98.  spartan. The problem arises here because we cannot set up the clipPanlView
  99.  using more conventional procedural techniques, as in the many examples ?}
  100.    clipDoc.DoClipViews;
  101.    clipPanlView := clipDoc.fBaseView;
  102.  
  103.    IF fView.Focus THEN ;
  104.  
  105.    CopyToClip;
  106.  
  107.    {Make sure the Cut left us with enough memory to continue.}
  108.    FailSpaceIsLow;
  109.    Success(fi);
  110.  
  111.    gApplication.ClaimClipboard(clipPanlView);
  112.  
  113.  {this final method call makes sure that all the altered views are
  114.  correctly filled, sized, topped & tailed}
  115.    UpdateViews;
  116. END;
  117.  
  118. The problem is that, on the third (and subsequent) clipboard command, when
  119. Application.AbandonUndoClipboard is called to dispose of gClipUndoView, there
  120. is confusion as to the existence of gClipUndoView - it is given as already
  121. being freed, but patently has not been freed!
  122.  
  123. Our kludge to work around this (far from elegant, but it works without any
  124. memory or handle leakage) is:
  125.  
  126. PROCEDURE TPanellistApplication.AbandonUndoClipboard; OVERRIDE;
  127.    VAR aDoc: TDocument;
  128.    BEGIN
  129.    IF gClipUndoView <> NIL THEN
  130.    BEGIN
  131.    {$IFC qDebug}
  132.    IF gClipUndoView = gClipView THEN
  133.    ProgramBreak('About to Free view both in clip and undo Clip!');
  134.    {$ENDC}
  135.    aDoc := gClipUndoView.fDocument;
  136.    IF (aDoc <> NIL) THEN TPanlDocument(aDoc).FreeForClip;
  137.  {note that if we do *not* call this, we just accumulate orphaned views and
  138. windows}
  139.    gClipUndoView := NIL;
  140.    END;
  141.    END;
  142.  
  143. PROCEDURE TPanlDocument.FreeForClip;
  144.    VAR wmgrWindow: WindowPtr;
  145.    BEGIN
  146.  {this is a paraphrased & reordered version of TDocument.Free which is the only
  147. one which actually works!}
  148.    fPanl.Free; {our local data object}
  149.    gApplication.DeleteDocument(SELF);
  150.    FreeIfObject(fBaseView); {*must* be here before freeing views etc., or it is
  151.                            given as being freed already}
  152.    wmgrWindow := fPanlTWindow.fWMgrWindow;
  153.    wmgrWindow := FreeIfWMgrWindow(wmgrWindow, TRUE); {dispose of  WMgr window}
  154.    fPanlTWindow.fSubViews.ShallowFree; {just get rid of the list - its contents
  155.                                       have already been freed!}
  156.    fPanlTWindow.ShallowFree; {just get rid of the window itself}
  157.    fWindowList.ShallowFree;  {just get rid of the window list itself, as its
  158.                             contents have already been disposed of}
  159.    fViewList.ShallowFree; {ditto for the view list}
  160.  
  161.  {and the rest is much the same as for TDocument.Free}
  162.    IF fSharePrintInfo THEN
  163.    fPrintInfo := DisposeIfHandle(fPrintInfo);
  164.    fPrintInfo := NIL;  { Always drop my reference }
  165.  
  166.    Handle(fTitle) := DisposeIfHandle(fTitle);
  167.    IF gTarget = SELF THEN
  168.    IF fNextHandler = NIL THEN
  169.    gApplication.SetTarget(gApplication)
  170.    ELSE
  171.    gApplication.SetTarget(fNextHandler);
  172.  
  173.    fNextHandler := NIL;
  174.    ShallowFree;
  175.    END;
  176.  
  177. There must be a more elegant solution - any ideas?
  178.  
  179. Regards & a very successful New Year,
  180. Howard Oakley.
  181.  
  182.